package cn.yuanqiao.archive.utils.impl;

import cn.yuanqiao.archive.utils.FilePageCounter;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

/**
 * @ClassName: ExcelFilePageCounter
 * @Description: 类的描述
 * @author: lihuahua
 * @date: 2024/4/11 17:21
 * @Blog: huahuacoco.top
 */

@Service("ExcelFilePageCounter")
public class ExcelFilePageCounter implements FilePageCounter {

    @Override
    public int getPageCount(String filePath) throws Exception {
        try (Workbook workbook = new XSSFWorkbook(new FileInputStream(filePath))) {
            return workbook.getNumberOfSheets();
        }
    }

    @Override
    public InputStream extractPages(String url, List<Integer> sheetIndices) throws Exception {
        // 加载源Excel文档
        Workbook workbook = new XSSFWorkbook(new FileInputStream(url));

        // 创建用于存储裁剪后工作表的新文档
        Workbook extractedWorkbook = new XSSFWorkbook();

        // 处理指定工作表索引范围
        for (Integer sheetIndex : sheetIndices) {
            // 校验工作表索引有效性
            if (sheetIndex <= 0 || sheetIndex > workbook.getNumberOfSheets()) {
                throw new IllegalArgumentException("Invalid sheet index: " + sheetIndex);
            }

            // 从源文档中复制指定工作表到新文档
            copySheet(workbook, extractedWorkbook, sheetIndex);
        }

        // 将裁剪后的Excel写入内存输出流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        extractedWorkbook.write(outputStream);
        extractedWorkbook.close();

        // 返回包含裁剪后Excel内容的输入流
        return new ByteArrayInputStream(outputStream.toByteArray());
    }

    private void copySheet(Workbook sourceWorkbook, Workbook destWorkbook, int sheetIndex) {
        Sheet sourceSheet = sourceWorkbook.getSheetAt(sheetIndex - 1); // 转换为零索引
        Sheet destSheet = destWorkbook.createSheet(sourceSheet.getSheetName());

        // 复制表头行（如果有）
        Row headerRow = sourceSheet.getRow(0);
        if (headerRow != null) {
            Row newHeaderRow = destSheet.createRow(0);
            copyRow(headerRow, newHeaderRow);
        }

        // 复制数据行
        for (int rowIndex = sourceSheet.getFirstRowNum(); rowIndex <= sourceSheet.getLastRowNum(); rowIndex++) {
            Row row = sourceSheet.getRow(rowIndex);
            if (row != null) {
                Row newRow = destSheet.createRow(destSheet.getLastRowNum() + 1);
                copyRow(row, newRow);
            }
        }
    }

    private void copyRow(Row sourceRow, Row destRow) {
        for (int colIndex = sourceRow.getFirstCellNum(); colIndex <= sourceRow.getLastCellNum(); colIndex++) {
            Cell sourceCell = sourceRow.getCell(colIndex);
            if (sourceCell != null) {
                Cell destCell = destRow.createCell(colIndex);
                copyCell(sourceCell, destCell);
            }
        }
    }

    private void copyCell(Cell sourceCell, Cell destCell) {
        switch (sourceCell.getCellType()) {
            case STRING:
                destCell.setCellValue(sourceCell.getStringCellValue());
                break;
            case NUMERIC:
                destCell.setCellValue(sourceCell.getNumericCellValue());
                break;
            case BOOLEAN:
                destCell.setCellValue(sourceCell.getBooleanCellValue());
                break;
            case FORMULA:
                destCell.setCellFormula(sourceCell.getCellFormula());
                break;
            case BLANK:
                destCell.setBlank();
                break;
            case ERROR:
                destCell.setCellErrorValue(sourceCell.getErrorCellValue());
                break;
            case _NONE:
                break;
            default:
                throw new IllegalStateException("Unknown cell type: " + sourceCell.getCellType());
        }
    }
}

